﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace BFTest.Classes
{
    abstract class CShootingClass : CUnit
    {
        abstract public float Accuracy { get; }
        abstract public int FireChance { get; }
        abstract public TimeSpan RateOfFire { get; }
        abstract public int MagSize { get; }
        abstract public TimeSpan TimeToReload { get; }

        int roundsInMag;
        protected int RoundsInMag { get { return roundsInMag; } set { roundsInMag = value; } }
        
        TimeSpan reloadTimer;
        public TimeSpan ReloadTimer { get { return reloadTimer; } private set { reloadTimer = value; } }

        public CShootingClass(int id, Vector2 position, string soldierName, UnitRank rank, int side, Texture2D texture)
            : base(id, position, soldierName, rank, side, texture)
        {
            this.Initialize();
        }

        protected override void Initialize()
        {
            RoundsInMag = MagSize;
            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            if (Status != UnitStatus.Dead)
            {
                // Check to see if there are any enemies alive
                CUnit firstLivingEnemy = null;
                List<CUnit> enemiesList;

                if (Side == 1)
                    enemiesList = BFTestGame.Battlefield.EnemyUnits;
                else if (Side == 2)
                    enemiesList = BFTestGame.Battlefield.PlayerUnits;
                else
                    throw new ArgumentException("Side", "Side must be 1 or 2.");

                foreach (CUnit unit in enemiesList)
                {
                    if (unit.Alive == true)
                    {
                        firstLivingEnemy = unit;
                        break;
                    }
                }

                if (firstLivingEnemy != null)
                {
                    // Start with the first enemy unit
                    Target = firstLivingEnemy;

                    foreach (CUnit unit in enemiesList)
                        // Check each unit to see if its closer than the last, resulting in the closest
                        if (unit.Alive && DistanceToUnit(unit) < DistanceToUnit(Target))
                            Target = unit;

                    // Get the direction to the nearest unit that was just found
                    Direction = Target.Position - Position;

                    // Shoot at the targeted unit
                    if (RoundsInMag == 0)
                    {
                        Status = UnitStatus.Reloading;
                        if (gameTime.TotalGameTime - LastShot >= TimeToReload)
                        {
                            Status = UnitStatus.Idle;
                            RoundsInMag = MagSize;
                        }
                    }
                    else
                    {
                        if (gameTime.TotalGameTime - LastShot >= RateOfFire)
                        {
                            if (BFTestGame.Battlefield.Rand.NextDouble() * 100 <= FireChance)
                            {
                                float offset = (float)((BFTestGame.Battlefield.Rand.NextDouble() * Accuracy) - (Accuracy / 2));
                                Direction = Direction.RotateVector(offset);
                                Shoot(Direction);
                            }
                            LastShot = gameTime.TotalGameTime;
                        }
                    }
                }
            }

            base.Update(gameTime);
        }

        protected override void DrawBefore(SpriteBatch spriteBatch)
        {
            base.DrawBefore(spriteBatch);
        }

        protected override void DrawAfter(SpriteBatch spriteBatch)
        {
            if (Alive && Status == UnitStatus.Reloading)
            {
                Rectangle reloadingRect = new Rectangle(
                        (int)(Position.X - (BFTestGame.Battlefield.ReloadingTexture.Width / 2)),
                        (int)(Position.Y - (BFTestGame.Battlefield.ReloadingTexture.Height / 2) - 20),
                        BFTestGame.Battlefield.ReloadingTexture.Width, BFTestGame.Battlefield.ReloadingTexture.Height);

                spriteBatch.Draw(BFTestGame.Battlefield.ReloadingTexture, reloadingRect, Color.White);
            }
            base.DrawAfter(spriteBatch);
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            base.Draw(spriteBatch);
        }
    }
}
